﻿using System.Windows;                       //STANDARD for WPF App
using System.Windows.Controls;              //STANDARD for WPF App

//STANDARD for WPF App
//STANDARD for WPF App
//For : InkCanvas
//For : ExecutedRoutedEventArgs
//For : DrawingAttributes
//For : XamlWriter
using System.Windows.Media;                 //For : DrawingGroup

//STANDARD for WPF App
//For : BitmapImage etc etc
//STANDARD for WPF App
using System.Windows.Shapes;                //For : Geometric shapes like Line

namespace BitsOfStuff
{
    /// <summary>
    /// Class that holds line of segment, abstract class. From this class is derivered CurvedLine and StraightLine
    /// </summary>
    public abstract class MyLine
    {
        /// <summary>
        /// Main item in this class, this vector contain information about shape of line
        /// </summary>
        public MyVector Vector;

        private int _sector;

        private int calculateSector(int[] axes, double devianceTolerance)
        {
            double angle = Vector.getVectorAngle();
            //string debug = String.Format("angel:{0}",
            //_vector.getVectorAngle().ToString());
            //Debug.WriteLine(debug);
            for (int i = 0; i < 4; i++)
            {
                if (axes[i] - devianceTolerance < angle && axes[i] + devianceTolerance > angle)
                    return i * 2;
            }
            for (int i = 0; i < 4; i++)
            {
                if (axes[i] - devianceTolerance < angle && axes[i + 1] + devianceTolerance > angle)
                    return i * 2 + 1;
            }

            if (axes[3] - devianceTolerance < angle && axes[0] + devianceTolerance > angle)
                return 7;

            return 7;
        }

        /// <summary>
        /// Constructor of myline , take two points for construct vector
        /// </summary>
        /// <param name="firsPoint">Start point of vector</param>
        /// <param name="secondPoint">End point of vecotr</param>
        public MyLine(MySelectedPoint firsPoint, MySelectedPoint secondPoint)
        {
            Vector.makeVector(firsPoint, secondPoint);
        }

        /// <summary>
        /// For some purpouse, we just create line based on points , so its like statick constructor of this object
        /// </summary>
        /// <param name="firsPoimt">Start point of vector</param>
        /// <param name="secondPoint">End point of vector</param>
        /// <returns></returns>
        public static MyLine createLine(MySelectedPoint firsPoimt, MySelectedPoint secondPoint)
        {
            StartEndPoint firsStartPoint = firsPoimt as StartEndPoint;
            StartEndPoint secondStartPoint = secondPoint as StartEndPoint;

            CordnerPoint firsCornerPoint = firsPoimt as CordnerPoint;
            CordnerPoint secondCornerPoint = secondPoint as CordnerPoint;

            CurvePoint firsCurvedPoint = firsPoimt as CurvePoint;
            CurvePoint secondCurvedPoint = secondPoint as CurvePoint;

            if (firsStartPoint != null)
            {
                if (secondStartPoint != null)
                    return new StreingtMyLine(firsPoimt, secondPoint);
                if (secondCornerPoint != null)
                    return new StreingtMyLine(firsPoimt, secondPoint);
                if (secondCurvedPoint != null)
                    return new CurvedMyLine(firsPoimt, secondPoint);
            }
            if (firsCornerPoint != null)
            {
                if (secondCornerPoint != null)
                    return new StreingtMyLine(firsPoimt, secondPoint);
                if (secondStartPoint != null)
                    return new StreingtMyLine(firsPoimt, secondPoint);
                if (secondCurvedPoint != null)
                    return new CurvedMyLine(firsPoimt, secondPoint);
            }
            if (firsCurvedPoint != null)
                return new CurvedMyLine(firsPoimt, secondPoint);
            return new CurvedMyLine(firsPoimt, secondPoint);
        }

        /// <summary>
        /// Function that convert myLine to Freeman chain code
        /// </summary>
        /// <param name="diversion">angle whitch is tolerated</param>
        /// <param name="axes">angle diversion of axes</param>
        /// <returns></returns>
        public int getFreemanCode(int diversion, int[] axes)
        {
            _sector = calculateSector(axes, MyParameters.shapeAxesDiversion);
            return _sector;
        }

        protected void drawn(InkCanvas inkCanvas, Brush brush)
        {
            var myMyLine = new Line
                               {
                                   Stroke = brush,
                                   X1 = Vector.getStartPoint().getPoint().getX(),
                                   X2 = Vector.getEndPoint().getPoint().getX(),
                                   Y1 = Vector.getStartPoint().getPoint().getY(),
                                   Y2 = Vector.getEndPoint().getPoint().getY(),
                                   HorizontalAlignment = HorizontalAlignment.Left,
                                   VerticalAlignment = VerticalAlignment.Center,
                                   StrokeThickness = 4
                               };
            //myMyLine.Stroke = System.Windows.Media.Brushes.Black;
            inkCanvas.Children.Add(myMyLine);
        }

        /// <summary>
        /// Function for visualizating line on inkCanvas
        /// </summary>
        /// <param name="inkCanvas">inkCanvas that display all data</param>
        public virtual void drawn(InkCanvas inkCanvas)
        {
            drawn(inkCanvas, Brushes.Black);
        }
    }

    /// <summary>
    /// Derivated claff from Myline, this represent line that is straigt - its make from corner or start points only
    /// </summary>
    public class StreingtMyLine : MyLine
    {
        /// <summary>
        /// Constructor of streight line
        /// </summary>
        /// <param name="a">start point of segment</param>
        /// <param name="b">end point of segment</param>
        public StreingtMyLine(MySelectedPoint a, MySelectedPoint b)
            : base(a, b)
        { }

        /// <summary>
        /// Function for visualizating line on inkCanvas
        /// </summary>
        /// <param name="inkCanvas">inkCanvas that display all data</param>
        public override void drawn(InkCanvas inkCanvas)
        {
            drawn(inkCanvas, Brushes.DarkGreen);
        }
    }

    /// <summary>
    ///
    /// </summary>
    public class CurvedMyLine : MyLine
    {
        /// <summary>
        /// Derivated claff from Myline, this represent line that is curved - its make from corner or start points and must contain at least one curved point
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        public CurvedMyLine(MySelectedPoint a, MySelectedPoint b)
            : base(a, b)
        { }

        /// <summary>
        /// Function for visualizating line on inkCanvas
        /// </summary>
        /// <param name="inkCanvas">inkCanvas that display all data</param>
        public override void drawn(InkCanvas inkCanvas)
        {
            drawn(inkCanvas, Brushes.DarkOrange);
        }
    }
}